/*	--- 备忘录 Memento ---


#	在不破坏【封装性】的前提下，捕获【一个对象的内部状态】，并在该对象之外保存这个状态。

=====================================================================


【备忘录模式】（Memento），主要用于【捕获一个对象的内部状态】，以便在【将来的某个时候】恢复【此状态】。

其实我们使用的【几乎所有软件】都用到了【备忘录模式】。

最简单的【备忘录模式】就是【保存到文件，打开文件】。

对于【文本编辑器】来说，保存就是把【TextEditor类】的【字符串】存储到【文件】，【打开】就是【恢复TextEditor类的状态】。

对于【图像编辑器】来说，原理是一样的，只是【保存和恢复】的【数据格式】比较复杂而已。

【Java的序列化】也可以看作是【备忘录模式】。

在使用【文本编辑器】的时候，我们还经常使用【Undo、Redo这些功能】。

这些其实也可以用【备忘录模式】实现，即【不定期地把TextEditor类的字符串】复制一份存起来，这样就可以Undo或Redo。


【标准的备忘录模式】有这么几种角色：
	· Memonto ：存储的【内部状态】；
	· Originator n. 创始人,首次提出者：创建一个【备忘录】并【设置其状态】；
	· Caretaker n. 看守人 ：负责【保存备忘录】。 


实际上我们在使用【备忘录模式】的时候，不必设计得这么复杂，只需要对【类似TextEditor的类】，增加【getState()和setState()】就可以了。

我们以一个【文本编辑器TextEditor】为例，它【内部使用StringBuilder】允许用户【增删字符】：
 */
public class TextEditor {
	private StringBuilder buffer = new StringBuilder();

	public void add(char ch) {
		buffer.append(ch);
	}

	public void add(String s) {
		buffer.append(s);
	}

	public void delete() {
		if (buffer.length() > 0) {
			buffer.deleteCharAt(buffer.length() - 1);
		}
	}
}

/*
为了支持【这个TextEditor】能【保存和恢复状态】

我们【增加 getState() 和 setState() 这两个方法】： */
public class TextEditor {
	//...

	// 获取状态
	public String getState() {
		return buffer.toString();
	}

	// 恢复状态
	public void setState(String state) { // state 是以前保存好的状态
		this.buffer.delete(0, this.buffer.length());
		this.buffer.append(state);
	}
}


/*
对这个简单的文本编辑器，用一个String就可以表示其状态，对于【复杂的对象模型】，通常我们会使用【JSON、XML等复杂格式】。


===========================================================


#	练习

给TextEditor添加备忘录模式  */
class PriceManagement implements ProductObserver {
	@Override
	public void on_Published(Product product) {
		System.out.println("[PriceManagement] on product published: " + product);
	}

	@Override
	public void on_Price_Changed(Product product) {
		System.out.println("[PriceManagement] on product price changed: " + product);
	}
}

public void addNewProduct(String name, double price) {
	Product p = new Product(name, price);
	products.put(p.getName(), p);

	observers.forEach(o -> new Thread() {
		@Override
		public void run() {
			o.on_Published(p);
		}
	}.start());
}

public void setProductPrice(String name, double price) {
	Product p = products.get(name);
	p.setPrice(price);

	observers.forEach(o -> new Thread() {
		public void run() {
			o.on_Price_Changed(p);
		}
	}.start());
}



/*===================================================


#	----- 备忘录 の 小结 -----

1. 【备忘录模式】是为了【保存对象的内部状态】，并在将来【恢复】，大多数软件提供的【保存、打开，以及编辑过程中的Undo、Redo】都是【备忘录模式的应用】。









































